home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / games2 / rotise12.zip / STRING.C < prev    next >
C/C++ Source or Header  |  1992-04-03  |  8KB  |  369 lines

  1. /* string.c -- String operations
  2.  
  3.     December 1989    Mark E. Mallett
  4.     Updated:
  5.         February 26, 1991    Jonathan Arnold
  6.  
  7. This file contains routines dealing with character strings.
  8. These include:
  9.  
  10.     tkline        Tokenize a line
  11.     gettoken        Extract a token from a string
  12.     strsicmp        stricmp that returns sign only.
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17.  
  18. #ifdef __TURBOC__
  19. #include <alloc.h>
  20. #else
  21. #include <malloc.h>
  22. #endif
  23.  
  24. #include "rotise.h"
  25.  
  26.  
  27. /* External data referenced */
  28.     /* NONE */
  29.  
  30. /* External routines used */
  31.     /* NONE */
  32.  
  33. /* Local data publicly available */
  34.     /* NONE */
  35.  
  36. /* Local routine prototypes */
  37. int tkline PROTO( (char *, char *, char **, int, char *, char *) );
  38. char *gettoken PROTO( (char *, char *, int, char *, char *) );
  39.  
  40. /* Private data */
  41.     /* NONE */
  42.  
  43. /* tkline( bufP, tbufP, tokcP, tokv, tokmax, vsepP, isepP )
  44.  
  45.     Tokenize a line of text
  46.  
  47. Accepts :
  48.  
  49.     bufP        The buffer containing data to be tokenized
  50.     tbufP        A buffer in which tokens will be placed
  51.     tokv        Ptr to tokv array -- ptrs to tokens
  52.     tokmax        Maximum number of tokens to return
  53.     vsepP, isepP    Separators, as in call to gettoken() (refer there)
  54.     
  55. Returns :
  56.  
  57.     <value>    Number of tokens extracted
  58.     *tokv        Ptrs to tokens
  59.  
  60. Notes :
  61.  
  62.     Caller must ensure that the token buffer is large enough to receive
  63.     all of the tokens.
  64.  
  65.     The source and destination buffers may overlap, as long as the
  66.     source buffer's address is greater than the token buffer's.  Thus,
  67.     &bufP[0] can be &tbufP[1] (this is a convenient arrangement).
  68.  
  69. */
  70.  
  71. int tkline ARGLIST( ( bufP, tbufP, tokv, tokmax, vsepP, isepP ) )
  72.     NFARG ( char *bufP )        /* Buffer ptr */
  73.     NFARG ( AREG1 char *tbufP)    /* Token buffer pointer */
  74.     NFARG ( AREG2 char **tokv)    /* Arg vectors */
  75.     NFARG ( int tokmax)        /* Max # tokens */
  76.     NFARG ( char *vsepP)        /* Visible separators */
  77.     FARG ( char *isepP)        /* Invisible separators */
  78. {
  79. DREG1    int        tokC;        /* # of tokens */
  80.  
  81.     /* Extract the tokens */
  82.     for( tokC = 0;
  83.         ( tokC < tokmax ) && 
  84.             ( bufP = gettoken( bufP, tbufP, 9999, vsepP, isepP ) ) != NULL;
  85.         ++tokC )
  86.     {
  87.         *tokv++ = tbufP;
  88.  
  89.         while( *tbufP++ != NUL  )
  90.             ;
  91.     }
  92.  
  93.   return( tokC );
  94. }    
  95. /* gettoken( strP, tokP, tokmax, vsepP, isepP )
  96.  
  97.     Extract a token from a string
  98.  
  99. Accepts :
  100.  
  101.     strP        Source string
  102.     tokP        Buffer to contain the token
  103.     tokmax        Maximum lenght of token (including NUL)
  104.     vsepP        "visible" separators -- chars that will terminate
  105.              and will also be returned as single-character tokens;
  106.     isepP        "invisible" separators -- chars that will terminate
  107.               a token and will be deleted from the source string.
  108.  
  109. Returns :
  110.  
  111.     <value>        Ptr to the rest of the string, or NULL if no
  112.              more tokens;
  113.     *tokP        Token extracted
  114.  
  115. */
  116.  
  117. char *gettoken ARGLIST( (strP, tokP, tokmax, vsepP, isepP ) )
  118.     NFARG (AREG1 char *strP)        /* Source string */
  119.     NFARG (AREG2 char *tokP)        /* Where to put token */
  120.     NFARG (int tokmax)        /* Max length of token */
  121.     NFARG (char *vsepP)        /* Visible separators */
  122.     FARG (char *isepP)        /* Invisible separators */
  123. {
  124. DREG1    char        ch;        /* Character */
  125. DREG3    char        quote;        /* Quoting character */
  126. DREG2    int        tokX;        /* Index into token string */
  127. AREG3    char        *sepP;        /* Ptr to separator */
  128.     static    char    sepmsk[128];    /* Separator mask array */
  129. #define    SEP_VIS        1
  130. #define    SEP_INVIS    2
  131.  
  132.     /* Trap NULL source string pointer */
  133.     if ( strP == NULL )
  134.         return( NULL );
  135.  
  136.     /* Preprocess separator arrays */
  137.     for( sepP = vsepP; ( ch = *sepP++ ) != NUL; )
  138.         sepmsk[ch] = SEP_VIS;
  139.     for( sepP = isepP; ( ch = *sepP++ ) != NUL; )
  140.         sepmsk[ch] |= SEP_INVIS;
  141.  
  142.     /* Strip leading "invisible" separators */
  143.     for( ; ( ( ch = *strP ) != NUL ) &&
  144.             ( ( sepmsk[ch] & SEP_INVIS ) != 0 ); )
  145.         ++strP;
  146.  
  147.     /* Check for quoted character string */
  148.     if ( ( ch == '"' ) || ( ch == '\'' ) ) {
  149.         quote = ch;
  150.         ++strP;
  151.     }
  152.     else
  153.         quote = NUL;
  154.  
  155.     /* Loop to get token characters */
  156.     for( tokX = 0; ( ch = *strP ) != NUL; ++strP ) {
  157.         /* Check for escaped character */
  158.         if ( ( ch == '\\' ) && ( strP[1] != NUL ) )
  159.             ch = *++strP;        /* Use the escaped char */
  160.  
  161.         /* Check for terminating quote */
  162.         else if ( ( quote != NUL ) && ( ch == quote ) ) {
  163.             quote = NUL;
  164.             ++strP;
  165.             break;
  166.         }
  167.  
  168.         /* Check for delimiter */
  169.         else if ( sepmsk[ ch ] != 0 ) {
  170.             /* If it's invisible, just skip it */
  171.             if ( ( sepmsk[ch] & SEP_INVIS ) != 0 )
  172.                 ++strP;
  173.             else {
  174.                 /* If visible, take it if it's the only char. */
  175.                 if ( tokX++ == 0 ) {
  176.                     *tokP++ = ch;
  177.                     ++strP;
  178.                 }
  179.             }
  180.             break;
  181.         }
  182.  
  183.         /* Add the character to the token */
  184.         if ( tokX++ < tokmax -1 )
  185.             *tokP++ = ch;
  186.     }
  187.  
  188.     *tokP = NUL;
  189.  
  190.     /* Check for end of string */
  191.     if ( ( tokX == 0 ) && ( ch == NUL ) )
  192.         strP = NULL;
  193.  
  194.     /* Undo the separator array marks */
  195.  
  196. /* On some systems, this might be faster.  */
  197. /*    memset( &sepmsk[0], 0, 128 );   */
  198.  
  199.     for( sepP = vsepP; ( ch = *sepP++ ) != NUL; )
  200.         sepmsk[ch] = 0;
  201.     for( sepP = isepP; ( ch = *sepP++ ) != NUL; )
  202.         sepmsk[ch] = 0;
  203.  
  204.    return( strP );
  205. }
  206. /*
  207.  
  208. *//* strscmp( str1P, str2P )
  209.  
  210.     Like strcmp() but return just the sign.
  211.  
  212. Accepts :
  213.  
  214.     str1P        First string
  215.     str2P        Second string
  216.  
  217. Returns :
  218.  
  219.     <value>        -1 if str1P < str2P     (stringwise, of course)
  220.              0 if str1P == str2P
  221.              1 if str1P > str2P
  222.  
  223. Notes :
  224.  
  225.     This mimics the "old" behaviour of strcmp().
  226.  
  227. */
  228.  
  229. int
  230. strscmp( str1P, str2P )
  231.     char        *str1P;        /* First string */
  232.     char        *str2P;        /* Second string */
  233. {
  234.     int        cmpval;        /* Comparison value */
  235.  
  236.     if ( ( cmpval = strcmp( str1P, str2P ) ) < 0 )
  237.     return( -1 );
  238.     else if ( cmpval == 0 )
  239.     return( 0 );
  240.     else
  241.     return( 1 );
  242. }
  243. /*
  244.  
  245. *//* stricmp() and strnicmp()
  246.  
  247.     Like strcmp() and strncmp() but ignoring case.  These may
  248.     not be present in the C library in use, in which case these
  249.     routines may be conditionally compiled.
  250.  
  251. */
  252.  
  253. #ifndef HAVE_STRICMP
  254.  
  255. #include <ctype.h>
  256.  
  257. int
  258. stricmp( s1, s2 )
  259. register char        *s1, *s2;
  260. {
  261. register unsigned char    c1, c2;
  262.  
  263.     for( ; ; ) {
  264.     c1 = *s1++;
  265.     c2 = *s2++;
  266.     if ( isupper( c1 ) )
  267.         c1 = tolower( c1 );
  268.     if ( isupper( c2 ) )
  269.         c2 = tolower( c2 );
  270.     if ( c1 < c2 )
  271.         return( -1 );
  272.     if ( c1 > c2 )
  273.         return( 1 );
  274.     if ( c1 == NUL )
  275.         return( 0 );
  276.     }
  277. }
  278.  
  279. int
  280. strnicmp( s1, s2, max )
  281. register char        *s1, *s2;
  282.     int        max;
  283. {
  284. register unsigned char    c1, c2;
  285.  
  286.     for( ; max > 0; --max ) {
  287.     c1 = *s1++;
  288.     c2 = *s2++;
  289.     if ( isupper( c1 ) )
  290.         c1 = tolower( c1 );
  291.     if ( isupper( c2 ) )
  292.         c2 = tolower( c2 );
  293.     if ( c1 < c2 )
  294.         return( -1 );
  295.     if ( c1 > c2 )
  296.         return( 1 );
  297.     if ( c1 == NUL )
  298.         return( 0 );
  299.     }
  300.     return( 0 );
  301. }
  302.  
  303. /* Chances are if you don't have stricmp, you don't have strupr */
  304. char *
  305. strupr( strP )
  306.     char        *strP;
  307. {
  308.     int        ch;
  309.     char        *workP;
  310.  
  311.     for ( workP = strP; ( ch = *workP ) != NUL; ++workP )
  312.     if ( islower( ch ) )
  313.         *workP = toupper( ch );
  314.  
  315.     return ( strP );
  316. }
  317.  
  318. #endif  /* HAVE_STRICMP */
  319.  
  320.  
  321. #if ultrix
  322. int
  323. memcmp( s1, s2, len )
  324.     UBYTE        *s1, *s2;
  325.     int        len;
  326. {
  327.     int        cmp;
  328.  
  329.     while( len-- > 0 )
  330.     if ( ( cmp = ( *s1++ - *s2++ ) ) != 0 )
  331.         return( cmp );
  332.     return( 0 );
  333. }
  334. #endif
  335.  
  336. /* strsicmp( str1P, str2P )
  337.  
  338.     Like stricmp() but return just the sign.
  339.  
  340. Accepts :
  341.  
  342.     str1P        First string
  343.     str2P        Second string
  344.  
  345. Returns :
  346.  
  347.     <value>        -1 if str1P < str2P     (stringwise, of course)
  348.              0 if str1P == str2P
  349.              1 if str1P > str2P
  350.  
  351. Notes :
  352.  
  353.  
  354. */
  355.  
  356. int strsicmp ARGLIST( (str1P, str2P) )
  357.     NFARG(    AREG1 char *str1P )        /* First string */
  358.     FARG(        AREG2    char *str2P )        /* Second string */
  359. {
  360. DREG1    int        cmpval;        /* Comparison value */
  361.  
  362.     if ( ( cmpval = stricmp( str1P, str2P ) ) < 0 )
  363.     return( -1 );
  364.     else if ( cmpval == 0 )
  365.     return( 0 );
  366.     else
  367.     return( 1 );
  368. }
  369.